import numpy as np
import time
import pandas as pd
from initdatabase import *
from interactdb import *


def huopan(sixty_nine_code, ref_price, platform, channel,
           activity_kind, activity_time,
           reference_begin_date, reference_end_date, rate_low=0.1, rate_ref=0.1):
    """
    sixty_nine_code: 69码
    platform: 平台，天猫/抖音，筛选
    channel: 前段输入值
    ref_price: 参考价（前端输入）
    activity_kind: 活动类型（前端输入）
    activity_time: 活动时间（前端输入）
    reference_begin_date: 参考销量情况的时间段开始时间（前端输入）
    reference_end_date: 参考销量情况的时间段结束时间（前端输入）
    rate_low: 最低价波动系数（前端输入）
    rate_ref: 参考价波动系数（前端输入）
    """

    # sixty_nine_code = '6921443500799'
    # reference_begin_date = '2024-01-18'
    # reference_end_date = '2024-01-20'
    # ref_price = 12
    # rate_low = 1
    # rate_ref = 1
    # platform = '天猫'
    # channel = '1'
    # activity_kind = '1'
    # activity_time = '1'

    """
    验证输入，如果不正确则直接返回
    """
    if ':' not in reference_begin_date:
        reference_begin_date += ' 00:00:00'
    if ':' not in reference_end_date:
        reference_end_date += ' 23:59:59'

    try:
        ref_price = float(ref_price)
        pass
    except:
        return ['参考价格式错误', pd.DataFrame()]

    try:
        rate_low = float(rate_low)
        pass
    except:
        return ['最低价波动系数错误', pd.DataFrame()]

    try:
        rate_ref = float(rate_ref)
        pass
    except:
        return ['参考价波动系数错误', pd.DataFrame()]

    """
    验证类型和时间是否有数值
    """
    if activity_kind == '':
        activity_kind = '-'
        pass

    if activity_time == '':
        activity_time = '-'
        pass

    global df_selected
    if platform == '天猫':
        df_selected = pd.read_sql_query(
            f"SELECT * FROM tmall_flagship_store_order_hour WHERE order_creation_time >= '{reference_begin_date}' AND order_creation_time <= '{reference_end_date}' AND sixty_nine_code = '{sixty_nine_code}'",
            engine)
    elif platform == '抖音':
        df_selected = pd.read_sql_query(
            f"SELECT * FROM dy_flagship_store_order_day WHERE order_creation_time >= '{reference_begin_date}' AND order_creation_time <= '{reference_end_date}' AND sixty_nine_code = '{sixty_nine_code}'",
            engine)

    df_selected.loc[:, 'year_month_day'] = df_selected['order_creation_time'].apply(lambda x: x.strftime('%Y-%m-%d'))

    if df_selected.empty:
        return ['69码在对应的时间段无销售', pd.DataFrame()]

    df_69_info = df_selected.loc[:, ['sixty_nine_code', 'good_product_combination', 'good_retail_price', 'good_series',
                                'good_initial_price', 'good_big_promotion_price', 'good_small_promotion_price',
                                'good_giveaway_item_price_ratio']].drop_duplicates()
    df_69_info = df_69_info[df_69_info['good_product_combination'] != '-1']

    """
    计算最低价附近的平均销量
    """
    global lowest_price
    lowest_price = df_selected['good_actual_price'].astype(float).min()
    # 计算时间段内最低价的  倍

    lowest_price = lowest_price * (1 + rate_low)
    # 计算时间段内最低价的  倍
    df_day_with_lowest_price = df_selected.groupby('year_month_day').apply(
        lambda x: (x['good_actual_price'] <= lowest_price).any())
    # 如果当天出现了最低价 倍以内的销售额，则作为销量参考
    df_day_with_lowest_price = df_day_with_lowest_price.reset_index()
    df_day_with_lowest_price.columns = ['year_month_day', 'has_lowest_price']
    df_selected = pd.merge(df_selected, df_day_with_lowest_price, on=['year_month_day'], how='left')
    # 附加上哪些天有最低价的标识（只要当日最低价低于该最低价，即纳入考虑）

    df_day_with_ref_price = df_selected.groupby('year_month_day').apply(
        lambda x: ((ref_price * (1 - rate_ref) <= x['good_actual_price']) &
                   (x['good_actual_price'] <= ref_price * (1 + rate_ref))).any()
    )
    df_day_with_ref_price = df_day_with_ref_price.reset_index()
    df_day_with_ref_price.columns = ['year_month_day', 'has_ref_price']
    df_selected = pd.merge(df_selected, df_day_with_ref_price, on=['year_month_day'], how='left')
    # 附加上哪些天有参考价的标识（只要当日存在与参考价相近的价格，即纳入考虑）

    base1 = df_selected[df_selected['has_lowest_price'] == True]['good_trans_count'].mean(skipna=True)
    if base1 is np.nan:
        return ['该产品在时间区间内，在某些时候未匹配上价格（价格体系表上传不及时）', pd.DataFrame()]

    # 得到base1，即最低价所在天的平均销量

    base2 = df_selected[df_selected['has_ref_price'] == True]['good_trans_count'].mean()
    if base2 is np.nan:
        return ['给定价格下，该时间段内无此商品', pd.DataFrame()]

    # 得到base2，即参考价所在天的平均销量

    predict_trans_multiple = base2 / base1
    predict_trans_count = base2
    predict_trans_amount = base2 * ref_price

    output_df = pd.DataFrame(
        {'查询时间': [time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))],
         '平台': [platform],
         '渠道': [channel],
         '活动类型': [activity_kind],
         '活动时间': [activity_time],
         '商品69码': [sixty_nine_code],

         '商品到手价': [ref_price],
         '参考数据起始日期': [reference_begin_date],
         '参考数据结束日期': [reference_end_date],
         '预测销售倍数': [predict_trans_multiple],  # 预测销售倍数 base2销量/base1销量
         '预测可销售件数': [predict_trans_count],  # 预测可销售件数 base2销量
         '预测销售额': [predict_trans_amount],  # 预测销售额 base2销量*商品到手价
         })

    output_df = output_df.merge(df_69_info, left_on=['商品69码'], right_on=['sixty_nine_code'], how='left')

    output_df['discount_rate'] = output_df['商品到手价'] / output_df['good_initial_price']
    output_df['fee_rate'] = (output_df['good_initial_price'] - output_df['商品到手价']) / output_df[
        'good_initial_price']

    output_df.rename(columns={'good_product_combination': '商品产品组合',
                              'good_series': '商品系列',
                              'good_retail_price': '零售价',
                              'good_initial_price': '开单价',
                              'good_big_promotion_price': '大促底价',
                              'good_small_promotion_price': '日促底价',
                              'good_giveaway_item_price_ratio': '赠品费率',
                              'discount_rate': '折扣率',
                              'fee_rate': '折扣费率'}, inplace=True)

    return ['成功', output_df]

# 返回的值是一个list，由一个字符串和一个pd dataframe组成；字符串如果提示'成功'或者'69码在69数据库中匹配不上'那就是(半)成功了，直接输出表即可。如果失败了，第一个字符串是提示，第二个是空的df。